//
//  cnm_https.swift
//  CNMHttps_Example
//
//  Created by MrHong on 2023/1/31.
//  Copyright © 2023 CocoaPods. All rights reserved.
//

import Alamofire

/// 响应成功key
public let successDataKey: String = "success_data"

/// 响应错误信息、错误码key
public let errorMessageKey: String = "error_message"
public let errorCodeKey: String = "error_code"

/// 请求类型
public enum CNMMethodType {
    case post
    case get
    case upload
}

/// 请求错误
public enum CNMHttpsError {
    /// 错误信息描述枚举
    enum CNMErrorMessge: String {
        case none = "抱歉，请求失败"
        case timeout = "抱歉，请求超时"
        case cancelled = "抱歉，请求取消"
        case cannotConnectToHost = "抱歉，连接服务器失败"
        case notConnectedToInternet = "抱歉，网络连接失败, 请检查网络"
        case badServerResponse = "抱歉，服务器未响应"
    }

    /// 根据 errorCode，返回错误信息
    static func errorMessge(code: Int) -> CNMErrorMessge {
        switch code {
        case NSURLErrorTimedOut:
            return CNMErrorMessge.timeout
        case NSURLErrorCancelled:
            return CNMErrorMessge.cancelled
        case NSURLErrorCannotConnectToHost:
            return CNMErrorMessge.cannotConnectToHost
        case NSURLErrorNotConnectedToInternet:
            return CNMErrorMessge.notConnectedToInternet
        case NSURLErrorBadServerResponse:
            return CNMErrorMessge.badServerResponse
        default:
            return CNMErrorMessge.none
        }
    }
}

public class CNMHttps {
    // Session实例
    private var sessionManager: Session?
    private let config = URLSessionConfiguration.af.default
    
    // 超时时长设置
    private var timeout: TimeInterval = 15 {
        didSet {
            config.timeoutIntervalForRequest = timeout
        }
    }
    

    // 单例
    private static let share = CNMHttps()
    private init() {
        config.timeoutIntervalForRequest = timeout // request 请求超时时间，默认60s
        config.timeoutIntervalForResource = 15 // 任务等待整个资源加载的超时时间（单位是秒）默认值是7天
        config.waitsForConnectivity = true // 是否应等待连接变为可用或者立即失败

        sessionManager = Session(configuration: config)
    }
    
    
    /// 设置请求超时时长
    /// - Parameters:
    ///     - time: 时长
    public static func cnm_setTimeout(time: Int) {
        CNMHttps.share.timeout = TimeInterval(time)
    }

    /// post 请求
    /// - Parameters:
    ///   - url: 请求地址
    ///   - parameters: 请求参数
    ///   - headers: 请求头
    ///   - success: 请求成功回调
    ///   - fail:请求失败回调
    public static func cnm_post(url: String,
                                parameters: Parameters? = nil,
                                headers: [String: String]? = nil,
                                success: @escaping (_ data: String) -> Void,
                                fail: @escaping (_ error: Dictionary<String, Any?>) -> Void) {
        // 添加请求头
        var http_headers: HTTPHeaders = ["Accept": "application/json"]
        if let _headers = headers, !_headers.isEmpty {
            for item in _headers {
                http_headers.add(name: item.key, value: item.value)
            }
        }

        // 请求
        CNMHttps.share.sessionManager?.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: http_headers).validate().response(completionHandler: { responseData in
            // 响应回调
            cnm_jsonResponse(responseData: responseData, success: success, fail: fail)
        })
    }

    /// get 请求
    /// - Parameters:
    ///   - url: 请求地址
    ///   - parameters: 请求参数
    ///   - headers: 请求头
    ///   - success: 请求成功回调
    ///   - fail:请求失败回调
    public static func cnm_get(url: String,
                               parameters: Parameters? = nil,
                               headers: [String: String]? = nil,
                               success: @escaping (_ data: String) -> Void,
                               fail: @escaping (_ error: Dictionary<String, Any?>) -> Void) {
        // 添加请求头
        var http_headers: HTTPHeaders = ["Accept": "application/json"]
        if let _headers = headers, !_headers.isEmpty {
            for item in _headers {
                http_headers.add(name: item.key, value: item.value)
            }
        }

        // 请求
        CNMHttps.share.sessionManager?.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: http_headers).validate().response(completionHandler: { (responseData: AFDataResponse<Data?>) in
            // 响应回调
            cnm_jsonResponse(responseData: responseData, success: success, fail: fail)
        })
    }

    /// 上传多张图片
    /// - Parameters:
    ///   - url: 请求地址
    ///   - parameters: 请求参数
    ///   - imgFiles: 图片文件集合；<服务端接收文件字段，<文件名，图片data数据流>>
    ///   - mimeType: 图片类型（png、jepg 等）
    public static func cnm_uploadImages(url: String,
                                        parameters: Dictionary<String, String>? = nil,
                                        imgFiles: Dictionary<String, Dictionary<String, Data?>>,
                                        mimeType: String = "image/jpeg",
                                        success: @escaping (_ data: String) -> Void,
                                        fail: @escaping (_ error: Dictionary<String, Any?>) -> Void) {
        CNMHttps.share.sessionManager?.upload(multipartFormData: { formData in
            // 拼接参数
            if let params = parameters, !params.isEmpty {
                for (key, value) in params {
                    formData.append(value.data(using: String.Encoding.utf8)!, withName: key)
                }
            }

            // 拼接数据流; withName：和后台服务器的name要一致
            if !imgFiles.isEmpty {
                for (serverName, file) in imgFiles {
                    for (fileName, data) in file {
                        if let imgData = data {
                            formData.append(imgData, withName: serverName, fileName: fileName, mimeType: mimeType)
                        }
                    }
                }
            }
        }, to: url).validate().response(completionHandler: { (responseData: AFDataResponse<Data?>) in
            // 相应回调
            cnm_jsonResponse(responseData: responseData, success: success, fail: fail)
        })
    }
}

// MARK: - Private Method

extension CNMHttps {
    /// 请求响应回调函数
    private static func cnm_jsonResponse(responseData: AFDataResponse<Data?>,
                                         success: (_ data: String) -> Void,
                                         fail: (_ error: Dictionary<String, Any?>) -> Void) {
        let statusCode = responseData.response?.statusCode
        
        print("错误：\(responseData.error?.errorDescription)");

        if statusCode != 200 {
            let message = CNMHttpsError.errorMessge(code: statusCode ?? -999).rawValue

            // 响应失败；则 fail 回调
            let errorMap: Dictionary<String, Any?> = [successDataKey: nil, errorMessageKey: message, errorCodeKey: statusCode ?? -999]
            fail(errorMap)

            return
        }

        guard let data = responseData.data else {
            // 响应成功，但结果 null；则 fail 回调
            let errorMap: Dictionary<String, Any?> = [successDataKey: nil, errorMessageKey: "\(responseData)", errorCodeKey: -999]
            fail(errorMap)
            return
        }

        // 解析响应data
        let jsonString = String(data: data, encoding: String.Encoding.utf8)

        if let json = jsonString {
            success(json)
        } else {
            // 响应成功，但结果 null；则 fail 回调
            let errorMap: Dictionary<String, Any?> = [successDataKey: nil, errorMessageKey: "\(responseData)", errorCodeKey: -999]
            fail(errorMap)
        }
    }
}
